package com.com.yunzong.rainbowbridge.command;

import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.com.yunzong.rainbowbridge.BridgeConfig;

import com.yz.jdd.base.utils.Constants;
import com.yz.jdd.base.utils.IOUtils;
import com.yz.jdd.base.utils.LogUtils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


public final class FileUtils {
    private static final String LOGTAG = BridgeConfig.LOG_TAG;
    private static final String ROOT_DIR = "yz";
    private static FileUtils fileUtils = new FileUtils();
    public static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/";
    public static final String FILE_NAME = "log";
    public static final String FILE_NAME_SUFFIX = ".txt";

    //压缩文件路径
    public static final String  ZIP_PATH= "com.yz.jdd/.zip/";

    //日志路径
    public static final String  LOG_PATH= "com.yz.jdd/.log/";
    private FileUtils() {
    }

    public static FileUtils getInstance() {
        return fileUtils;
    }

    /**
     * 获取SDCARD根路径
     *
     * @return
     */
    private static StringBuffer getRootDir() throws Exception {
        return new StringBuffer().append(Environment
                .getExternalStorageDirectory());
    }

    /**
     * 获取存在SDCARD上文件的绝对路径
     *
     * @param mContext
     * @param folderName
     * @param fileName
     * @return
     * @throws Exception
     */
    public static StringBuffer getExternalFileAbsoluteDir(Context mContext,
                                                          String folderName, String fileName) throws Exception {
        StringBuffer stringBuffer = getRootDir().append(File.separator);
        stringBuffer.append(getExternalFilesDir(mContext, folderName));
        if (fileName != null) {
            if (0 == fileName.indexOf(File.separator)) {
                stringBuffer.append(fileName);
            } else {
                stringBuffer.append(File.separator);
                stringBuffer.append(fileName);
            }
        }
        return stringBuffer;
    }

    /**
     * 在SDCARD上应用存储路径中创建文件
     *
     * @param mContext
     * @param folderName e.g. /xxx/xxx or xxx/xxx
     * @param fileName   e.g. xxx.png or /xxx.png
     * @return
     * @throws Exception
     */
    public static File createExternalFile(Context mContext, String folderName,
                                          String fileName) throws Exception {
        File file = new File(getExternalFileAbsoluteDir(mContext, folderName,
                fileName).toString());
        if (!file.exists())
            createExternalFilesDir(getExternalFilesDir(mContext, folderName));
        return file;
    }

    /**
     * 获取SDCARD上应用存储路径
     *
     * @param mContext
     * @param folderName
     * @return
     */
    private static StringBuffer getExternalFilesDir(Context mContext,
                                                    String folderName) throws Exception {
        String packageName = mContext.getPackageName();
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("Android").append(File.separator).append("data")
                .append(File.separator).append(packageName);
        if (folderName != null) {
            if (0 == folderName.indexOf(File.separator)) {
                stringBuffer.append(folderName);
            } else {
                stringBuffer.append(File.separator);
                stringBuffer.append(folderName);
            }
        }
        LogUtils.Log(LOGTAG, "FileUtils getExternalFilesDir "
                + stringBuffer.toString());
        return stringBuffer;
    }

    /**
     * 在SDCARD上创建应用存储路径
     *
     * @param stringBuffer
     * @return
     * @throws IOException
     */
    public static String createExternalFilesDir(StringBuffer stringBuffer)
            throws Exception {
        String[] paths = stringBuffer.toString().split(File.separator);
        stringBuffer.delete(0, stringBuffer.length());
        File file = null;
        for (String path : paths) {
            stringBuffer.append(path).append(File.separator);
            file = new File(getRootDir().append(File.separator)
                    .append(stringBuffer).toString());
            if (!file.exists()) {
                file.mkdir();
                LogUtils.Log(LOGTAG,
                        "FileUtils createExternalFilesDir create Dir "
                                + file.getAbsolutePath());
            }
        }
        return file != null ? file.getAbsolutePath() : null;
    }

    /**
     * 判断文件是否存在
     *
     * @param mContext
     * @param folderName
     * @param fileName
     * @return true if exist, else false
     * @throws Exception
     */
    public boolean isExternalFileExist(Context mContext, String folderName,
                                       String fileName) throws Exception {
        File file = new File(getExternalFileAbsoluteDir(mContext, folderName,
                fileName).toString());
        return file.exists();
    }

    /**
     * 判断文件是否存在
     *
     * @param url
     * @return
     */
    public static boolean isExists(String url) {
        if (TextUtils.isEmpty(url)) {
            return false;
        }
        File file = new File(url);
        return file.exists();
    }

    /**
     * 删除文件
     *
     * @param mContext
     * @param folderName
     * @param fileName
     * @throws Exception
     */
    public static void deleteExternalFile(Context mContext, String folderName,
                                          String fileName) throws Exception {
        String fileDir = getExternalFileAbsoluteDir(mContext, folderName,
                fileName).toString();
        File file = new File(fileDir);
        if (file.exists()) {
            file.delete();
            LogUtils.Log(LOGTAG, "FileUtils deleteExternalFile "
                    + fileDir);
        }
    }

    /**
     * 删除指定路径的文件夹
     *
     * @param mContext
     * @param folderName
     * @throws Exception
     */
    public void deleteExternalFilesDir(Context mContext, String folderName)
            throws Exception {
        String folderDir = getExternalFilesDir(mContext, folderName).toString();
        File externalFilesDir = new File(folderDir);
        deleteExternalFilesDir(externalFilesDir);
        LogUtils.Log(LOGTAG, "FileUtils deleteExternalFilesDir "
                + folderDir);
    }

    /**
     * 删除指定路径的文件夹
     *
     * @param externalFilesDir
     * @throws Exception
     */
    public void deleteExternalFilesDir(File externalFilesDir) throws Exception {
        if (externalFilesDir.isDirectory()) {
            File[] files = externalFilesDir.listFiles();
            for (File file : files) {
                deleteExternalFilesDir(file);
            }
            externalFilesDir.delete();
        } else {
            externalFilesDir.delete();
        }
    }

    /**
     * 将字节数组写入到SDCARD文件，如果文件不存在将自动创建该文件。
     *
     * @param mContext
     * @param folderName
     * @param fileName
     * @param bytes
     * @return
     * @throws Exception 返回 null
     */
    public File writeToExternalFilesDir(Context mContext, String folderName,
                                        String fileName, byte[] bytes) throws Exception {
        OutputStream os = null;
        String fileDir = getExternalFileAbsoluteDir(mContext, folderName,
                fileName).toString();
        File file = new File(fileDir);
        try {
            if (!file.exists()) {
                createExternalFilesDir(getExternalFilesDir(mContext, folderName));
            }
            os = new FileOutputStream(file);
            os.write(bytes);
            os.flush();
        } catch (IOException e) {
            return null;
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * 将流写入到SDCARD文件，如果文件不存在将自动创建该文件。
     *
     * @param mContext
     * @param folderName
     * @param fileName
     * @param is
     * @return
     * @throws Exception 返回 null
     */
    public File writeToExternalFilesDir(Context mContext, String folderName,
                                        String fileName, InputStream is) throws Exception {
        OutputStream os = null;
        String fileDir = getExternalFileAbsoluteDir(mContext, folderName,
                fileName).toString();
        LogUtils.Log(LOGTAG, "FileUtils writeToExternalFilesDir "
                + fileDir);
        File file = new File(fileDir);
        try {
            if (!file.exists()) {
                createExternalFilesDir(getExternalFilesDir(mContext, folderName));
            }
            os = new FileOutputStream(file);
            byte[] buffer = new byte[4 * 1024];
            while (is.read(buffer) != -1) {
                os.write(buffer);
            }
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * 截取url，获取文件名
     *
     * @param url
     * @return
     * @throws Exception
     */
    public String getFileName(String url) throws Exception {
        String fileName = url.substring(url.lastIndexOf(File.separator) + 1,
                url.length());
        LogUtils.Log(LOGTAG, "FileUtils getFileName " + fileName);
        return fileName;
    }

    /**
     * 把数据写入文件
     *
     * @param is       数据流
     * @param path     文件路径
     * @param recreate 如果文件存在，是否需要删除重建
     * @return 是否写入成功
     */
    public static boolean writeFile(InputStream is, String path,
                                    boolean recreate) {
        boolean res = false;
        File f = new File(path);
        FileOutputStream fos = null;
        try {
            if (recreate && f.exists()) {
                f.delete();
            }
            if (!f.exists() && null != is) {
                File parentFile = new File(f.getParent());
                parentFile.mkdirs();
                int count = -1;
                byte[] buffer = new byte[1024];
                fos = new FileOutputStream(f);
                while ((count = is.read(buffer)) != -1) {
                    fos.write(buffer, 0, count);
                }
                res = true;
            }
        } catch (Exception e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(fos);
            IOUtils.close(is);
        }
        return res;
    }

    /**
     * 判断SD卡是否挂载
     */
    public static boolean isSDCardAvailable() {
        return Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState());
    }

    /**
     * 获取SD下的应用目录
     */
    public static String getExternalStoragePath() {
        String sb = Environment.getExternalStorageDirectory().getAbsolutePath() +
                File.separator +
                ROOT_DIR +
                File.separator;
        return sb;
    }

    /** 获取应用的cache目录 */
//	public static String getCachePath() {
//
//		File f = BaseApplication.getInstance().getCacheDir();
//		if (null == f) {
//			return null;
//		} else {
//			return f.getAbsolutePath() + "/";
//		}
//	}

    /**
     * 创建文件夹
     */
    public static boolean createDirs(String dirPath) {
        File file = new File(dirPath);
        return !(!file.exists() || !file.isDirectory()) || file.mkdirs();
    }

    /** 获取应用data/data目录 */
//	public static String getFileDir() {
//		return BaseApplication.getInstance().getFilesDir().getAbsolutePath();
//	}

    /** 获取应用目录，当SD卡存在时，获取SD卡上的目录，当SD卡不存在时，获取应用的cache目录 */
//	public static String getDir(String name) {
//		StringBuilder sb = new StringBuilder();
//		if (isSDCardAvailable()) {
//			sb.append(getExternalStoragePath());
//		} else {
//			sb.append(getCachePath());
//		}
//		sb.append(name);
//		sb.append(File.separator);
//		String path = sb.toString();
//		if (createDirs(path)) {
//			return path;
//		} else {
//			return null;
//		}
//	}

    /**
     * @param content 需要写入的字符串
     * @param path    文件路径名称
     * @param append  是否以添加的模式写入
     * @return 是否写入成功
     */
    public static boolean writeFile(byte[] content, String path, boolean append) {
        boolean res = false;
        // File f = new File(getDir("yz") + "/" + path);
        File f = new File(path);
        RandomAccessFile raf = null;

        try {
            if (f.exists()) {
                if (!append) {
                    f.delete();
                    f.createNewFile();
                }
            } else {
                f.createNewFile();
            }
            if (f.canWrite()) {
                raf = new RandomAccessFile(f, "rw");
                raf.seek(raf.length());
                raf.write(content);
                res = true;
            }
        } catch (Exception e) {
            LogUtils.e(e);
        } finally {
            IOUtils.close(raf);
        }

        return res;
    }

    /**
     * 把字符串数据写入文件
     *
     * @param content 需要写入的字符串
     * @param path    文件路径名称
     * @param append  是否以添加的模式写入
     * @return 是否写入成功
     */
    public static boolean writeFile(String content, String path, boolean append) {
        return writeFile(content.getBytes(), path, append);
    }

    public static String getFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return null;
        } else {
            try {
                FileInputStream fis = new FileInputStream(file);
                byte[] buf = new byte[fis.available()];
                fis.read(buf);
                IOUtils.close(fis);
                return new String(buf);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
    }

    public String formatFileSize(long fileS) {
        DecimalFormat format = new DecimalFormat("#.00");
        String fileSizeString = "";
        if (fileS < 1024) {
            fileSizeString = format.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = format.format((double) fileS / 1024) + "K";
        } else if (fileS < 1073741824) {
            fileSizeString = format.format((double) fileS / 1048576) + "M";
        } else {
            fileSizeString = format.format((double) fileS / 1073741824) + "G";
        }
        return fileSizeString;
    }

    private long getFileSize(File file) {
        long size = 0;
        File flist[] = file.listFiles();
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getFileSize(flist[i]);
            } else {
                size = size + flist[i].length();
            }
        }
        return size;
    }

    public String getFileSize(Context mContext) {
        StringBuffer stringBuffer;
        try {
            stringBuffer = getRootDir()
                    .append(File.separator);
            String packageName = mContext.getPackageName();
            stringBuffer.append("Android").append(File.separator)
                    .append("data").append(File.separator).append(packageName);
            File file = new File(stringBuffer.toString());
            return formatFileSize(getFileSize(file));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "0";
    }

    /**
     * 复制单个文件
     *
     * @param oldPath String 原文件路径 如：c:/fqf.txt
     * @param newPath String 复制后路径 如：f:/fqf.txt
     * @return boolean
     */
    public static void copyFile(String oldPath, String newPath) {
        try {
            int bytesum = 0;
            int byteread = 0;
            File oldfile = new File(oldPath);
            if (oldfile.exists()) { // 文件存在时
                InputStream inStream = new FileInputStream(oldPath); // 读入原文件
                FileOutputStream fs = new FileOutputStream(newPath);
                byte[] buffer = new byte[1444];
                int length;
                while ((byteread = inStream.read(buffer)) != -1) {
                    bytesum += byteread; // 字节数 文件大小
                    // System.out.println(bytesum);
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
            }
        } catch (Exception e) {
            System.out.println("复制单个文件操作出错");
            e.printStackTrace();

        }

    }

    /**
     * 删除文件夹以及目录下的文件
     *
     * @param filePath 被删除目录的文件路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String filePath) {
        boolean flag = false;
        // 如果filePath不以文件分隔符结尾，自动添加文件分隔符
        if (!filePath.endsWith(File.separator)) {
            filePath = filePath + File.separator;
        }
        File dirFile = new File(filePath);
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        flag = true;
        File[] files = dirFile.listFiles();
        // 遍历删除文件夹下的所有文件(包括子目录)
        for (int i = 0; i < files.length; i++) {
            if (files[i].isFile()) {
                // 删除子文件
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) {
                    break;
                }
            } else {
                // 删除子目录
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) {
                    break;
                }
            }
        }
        if (!flag) {
            return false;
        }
        // 删除当前空目录
        return dirFile.delete();
    }

    /**
     * 删除单个文件
     *
     * @param filePath 被删除文件的文件名
     * @return 文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String filePath) {
        File file = new File(filePath);
        return file.isFile() && file.exists() && file.delete();
    }

    /**
     * 根据路径删除指定的目录或文件，无论存在与否
     *
     * @param filePath 要删除的目录或文件
     * @return 删除成功返回 true，否则返回 false。
     */
    public static boolean DeleteFolder(String filePath) {
        File file = new File(filePath);
        if (!file.exists()) {
            return false;
        } else {
            if (file.isFile()) {
                // 为文件时调用删除文件方法
                return deleteFile(filePath);
            } else {
                // 为目录时调用删除目录方法
                return deleteDirectory(filePath);
            }
        }
    }

    /**
     * 字符串写入sdcard中
     *
     * @param context 上下文
     * @param content 要写入字符串
     * @return 写入是否成功
     */
    public static boolean writeFileToSDCard(Context context, String content) {
        //如果SD卡不存在或无法使用，则无法把异常信息写入SD卡
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Log.w("writeFileToSDCard:", "SD卡不存在或无法使用...");
            return false;
        }
        //判断文件夹是否存在
        String FolderPath = PATH + context.getApplicationContext().getPackageName() + "/log/";
        File dir = new File(FolderPath);
        if (!dir.exists()) {
            dir.mkdirs();
        } else {
            //控制文件夹下只保留三个日志文件
            controlFileNum(context, 3);
        }

        long current = System.currentTimeMillis();
        String timeNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date(current));
        String filePath = FolderPath + FILE_NAME + timeNow + FILE_NAME_SUFFIX;
        File file = new File(filePath);

        try {
            FileWriter fw = new FileWriter(filePath, file.exists());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content + "\r\n ");
            bw.write("\r\n ");
            bw.close();
            fw.close();
        } catch (Exception e) {
            Log.w("writeFileToSDCard:", e.getMessage());
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 获取日志压缩文件路径
     *
     * @param
     * @return 路径
     */
    public static String zipFolder() {
        long current = System.currentTimeMillis();

        String timeNow = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(current));
        String folderPath = PATH + ZIP_PATH;
        File dir = new File(folderPath);
        //判断文夹是否存在，存在就删掉 清空 最终只保留一个压缩包
        if (dir.exists()) {
            boolean flag = FileUtils.deleteDirectory(folderPath);
            Log.w("", "是否删除成功？----->" + flag);
        }
        dir.mkdirs();
        String FolderPath = folderPath + "zip" + timeNow + ".zip";
        try {
            zipFolder(PATH + LOG_PATH, FolderPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return FolderPath;
    }

    /**
     * 压缩文件,文件夹
     *
     * @param srcFilePath 要压缩的文件/文件夹名字
     * @param zipFilePath 指定压缩的目的和名字
     * @throws Exception
     */
    public static void zipFolder(String srcFilePath, String zipFilePath) throws Exception {
        //创建Zip包
        java.util.zip.ZipOutputStream outZip =
                new java.util.zip.ZipOutputStream(new FileOutputStream(zipFilePath));

        //打开要输出的文件
        File file = new File(srcFilePath);

        //压缩
        zipFiles(file.getParent() + File.separator, file.getName(), outZip);

        //完成,关闭
        outZip.finish();
        outZip.close();

    }//end of func

    /**
     * 压缩文件
     *
     * @param folderPath
     * @param filePath
     * @param zipOut
     * @throws Exception
     */
    private static void zipFiles(String folderPath, String filePath,
                                 java.util.zip.ZipOutputStream zipOut) throws Exception {
        if (zipOut == null) {
            return;
        }

        File file = new File(folderPath + filePath);

        //判断是不是文件
        if (file.isFile()) {
            java.util.zip.ZipEntry zipEntry = new java.util.zip.ZipEntry(filePath);
            FileInputStream inputStream = new FileInputStream(file);
            zipOut.putNextEntry(zipEntry);

            int len;
            byte[] buffer = new byte[4096];

            while ((len = inputStream.read(buffer)) != -1) {
                zipOut.write(buffer, 0, len);
            }
            zipOut.closeEntry();
        } else {
            //文件夹的方式,获取文件夹下的子文件
            String[] fileList = file.list();

            //如果没有子文件, 则添加进去即可
            if (fileList == null && fileList.length <= 0) {
                java.util.zip.ZipEntry zipEntry = new java.util.zip.ZipEntry(filePath + File.separator);
                zipOut.putNextEntry(zipEntry);
                zipOut.closeEntry();
            } else {
                //如果有子文件, 遍历子文件
                for (int i = 0; i < fileList.length; i++) {
                    zipFiles(folderPath, filePath + File.separator + fileList[i], zipOut);
                }
            }
        }
    }

    /**
     * 获取文件夹下文件名日期列表
     *
     * @param folderPath 文件夹
     * @return
     */
    public static String[] getFileNames(String folderPath) {
        File[] array = new File(folderPath).listFiles();
        if (array == null || array.length == 0) {
            return null;
        }
        String[] arrayName = new String[array.length];
        for (int i = 0; i < array.length; i++) {
            arrayName[i] = array[i].getName().substring(3, 13);
        }
        //排序从小到大
//        PublicTools.strSort(arrayName);
        return arrayName;
    }


    /**
     * 控制文件夹文件数量
     *
     * @param context
     * @param num     文件数量
     * @return
     */
    public static boolean controlFileNum(Context context, int num) {
        boolean flag = false;
        String[] arrayName = FileUtils.getFileNames(PATH + context.getApplicationContext().getPackageName() + "/log/");
        if (arrayName != null && arrayName.length > num) {
            String filePath = PATH + context.getApplicationContext().getPackageName() + "/log/log" + arrayName[0] + ".txt";
            flag = FileUtils.deleteFile(filePath);
        }
        return flag;
    }

    /**
     * 字符串写入sdcard中
     *
     * @param content  要写入字符串
     * @param path     文件路径 默认为根路径/yunzong/
     * @param fileName 文件名称
     * @return 写入是否成功
     */
    public static boolean writeFileToSDCard(String content, String path, String fileName) {
        //如果SD卡不存在或无法使用，则无法把异常信息写入SD卡
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Log.w("writeFileToSDCard:", "SD卡不存在或无法使用...");
            return false;
        }
        if (TextUtils.isEmpty(content)) {
            return false;
        }
        String FolderPath;
        //判断文件夹是否存在
        if (TextUtils.isEmpty(path)) {
            FolderPath = PATH +Constants.BRAND_NAME_EN+ "/";
        } else {
            FolderPath = path;
        }
        File dir = new File(FolderPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        String filePath = FolderPath + fileName;
        File file = new File(filePath);
        try {
            FileWriter fw = new FileWriter(file, false);
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content + "\r\n ");
//			bw.write("\r\n ");
            bw.close();
            fw.close();
        } catch (Exception e) {
            Log.w("writeFileToSDCard:", e.getMessage());
            e.printStackTrace();
            return false;
        }

        return true;
    }


    /**
     * 读取文件
     *
     * @param path
     * @return
     */
    public static String readFile(String path) {
        try {
            if (TextUtils.isEmpty(path)) {
                return "";
            }
            File file = new File(path);
            if (!file.exists()) {
                return "";
            }
            BufferedReader br = new BufferedReader(new FileReader(file));
            String readLine;
            StringBuffer sb = new StringBuffer();
            while ((readLine = br.readLine()) != null) {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
}
